/* header.h, Ait, BSD 3-Clause, Kevin Bloom, 2023-2025,
   Derived from: Atto January 2017
   Derived from: Anthony's Editor January 93
*/
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <wchar.h>
#include "termbox.h"
int mkstemp(char *);

#if defined(__APPLE__) || defined(__NetBSD__)
#define st_atim st_atimespec
#define st_ctim st_ctimespec
#define st_mtim st_mtimespec
#endif

#define VERSION	 "Ait 1.12, BSD 3-Clause, 2025, by Kevin Bloom,  No warranty."
#define PROG_NAME "ait"
#define B_MODIFIED	0x01		/* modified buffer */
#define B_OVERWRITE	0x02		/* overwrite mode */
#define NOMARK          -1
#define CHUNK           8096L
#define K_BUFFER_LENGTH 256
#define TEMPBUF         1024
#define STRBUF_L        256
#define STRBUF_M        64
#define STRBUF_S        64
#define MIN_GAP_EXPAND  512
#define TEMPFILE        "/tmp/feXXXXXX"
#define F_NONE          0
#define F_CLEAR         1
#define ID_DEFAULT         1
#define ID_SYMBOL          2
#define ID_MODELINE        3
#define ID_DIGITS          4
#define ID_LINE_COMMENT    5
#define ID_BLOCK_COMMENT   6
#define ID_DOUBLE_STRING   7
#define ID_SINGLE_STRING   8
#define ID_REGION          9
#define ID_BACK_STRING     10
#define ID_FUNCTION        11
#define ID_CONSTANT        12

#define TRUE               1
#define FALSE              0

#define TAB_SIZE     8
#define TAB_SPACE_SIZE     2

#define PMARK_SIZE     10
#define KILLRING_SIZE     10
#define SHELLRING_SIZE     15

typedef unsigned char char_t;
typedef long point_t;

#define UA_NOTHING          0
#define UA_REPEAT           1
#define UA_CUSTOM           2
#define UA_PREVENT          3
#define KBD_MACRO           4

#define KBD_DEFAULT         0
#define KBD_INSERT          1
#define KBD_DELETE_CHAR     2
#define KBD_CUT             3
#define KBD_UNDO            4
#define KBD_DELETE_WORD     5
#define KBD_YANK            6
#define KBD_EXPAND          7

/* Window modes

*/
#define WINDOW_ERROR        0
#define WINDOW_DEFAULT      1
#define WINDOW_HORIZ        2
#define WINDOW_VERT         3
#define WINDOW_TRIHORIZ     4
#define WINDOW_TRIVERT      5
#define WINDOW_FIBLEFT      6
#define WINDOW_FIBRIGHT     7
#define WINDOW_QUAD         8
#define WINDOW_OTHER        9

typedef struct keymap_t {
	char *key_desc;                 /* name of bound function */
	int key_mod;		/* Termbox modifier number */
  int *key_bytes;             /* Array of Termbox key or char numbers */
	void (*func)(void);
  int universal_argument_action;
} keymap_t;

typedef struct syntax_t {
  char *word;
  int color;
} syntax_t;

typedef struct smode_t {
  char *extension;                 /* file extension */
  char *slc;       /* Single Line Comment */
  char *mlc;       /* Multiple Line Comment */
  char *emlc;       /* Multiple Line Comment End */
  int  sqas;       /* Single Quote As String */
  int  bqas;       /* Back Quote As String */
  const char saiv[5];       /* Symbols Allowed In Variables */
  int  bmls;       /* Backslash for Multiple Line String */
  syntax_t *keywords;
} smode_t;

typedef struct undo_t {
  point_t u_point;      /* point at which the undo happens */
  char_t *u_data;       /* data effected by the undo */
  unsigned long u_size;           /* used only for REPLACE & LOAD */
  int u_line;           /* original line number */
  int u_adjust;         /* should we adjust the point after undoing? */
  enum {
    INSERT = 1,
    DELETE,
    BACKSP,
    CUT,
    YANK,
    REPLACE,
    CLIPBOARD,
    LOAD,
  } u_type;
  struct undo_t *u_next;    /* next undo in the trail */
} undo_t;


typedef struct dynars_t {
  char_t *result;
  struct dynars_t *d_next;
} dynars_t;

typedef struct dyna_t {
  char_t *query;                 /* the query */
  int nquery;           /*  size of the query */
  point_t start;       /* The beginning of the query in the buffer */
  point_t end;         /* The end of the query in the buffer */
  point_t sp;       /* The Search Point, where we've searched already */
  int nresult;
  dynars_t *results;
} dyna_t;


typedef struct buffer_t
{
	struct buffer_t *b_next;  /* Link to next buffer_t */
	struct buffer_t *b_prev;  /* Link to prev buffer_t */
	point_t b_mark;           /* the mark */
	point_t b_pmark[PMARK_SIZE]; /* the previous marks */
	point_t b_point;          /* the point */
	point_t b_cpoint;         /* the original current point, used for multiple window displaying */
	point_t b_opoint;         /* orignial point */
	point_t b_page;           /* start of page */
	point_t b_opage;          /* original start of page */
	point_t b_epage;          /* end of page */
	int b_reframe;        /* force a reframe of the display */
	int b_cnt;                /* count of windows referencing this buffer */
	int b_size;               /* current size of text being edited (not including gap) */
	int b_psize;              /* previous size */
	char_t *b_buf;            /* start of buffer */
	char_t *b_ebuf;           /* end of buffer */
	char_t *b_gap;            /* start of gap */
	char_t *b_egap;           /* end of gap */
	int b_row;                /* cursor row */
	int b_col;                /* cursor col */
	int b_pcol;               /* previous cursor col */
	int b_line;              /* current line */
	char b_fname[PATH_MAX + 1]; /* filename */
	size_t b_fmtime;
	char b_bname[STRBUF_L];    /* buffer name */
	char b_flags;              /* buffer flags */
	undo_t b_ubuf[STRBUF_M];   /* undoset */
	undo_t *b_undo;            /* start of undo */
	undo_t *b_redo;            /* start of redo */
	int b_path;                /* does the buffer point to a real path */
	smode_t *b_mode;
} buffer_t;

typedef struct window_t
{
	struct window_t *w_next;   /* Next window */
	struct buffer_t *w_bufp;   /* Buffer displayed in window */
	point_t w_point;
	point_t w_mark;
	point_t w_page;
	point_t w_epage;
	int w_top;	    /* Origin 0 top row of window */
	int w_left;	    /* Origin 0 left-most column of window */
	int w_rows;        /* no. of rows of text in window */
	int w_cols;        /* no. of cols of text in window */
	int w_row;          /* cursor row */
	int w_col;          /* cursor col */
	int w_pcol;          /* previous cursor col */
	int w_update;
	char w_name[STRBUF_S];
	int w_mcol;         /* the last longest column (for rendering) */
	int w_mlen;         /* length of the modeline */
	int w_recenter;     /* force recenter */
	int w_hilite;       /* starting state for highlight */
} window_t;


typedef struct kill_t {
  char_t *data;
  point_t len;
} kill_t;

extern buffer_t *curbp;			/* current buffer */
extern buffer_t *bheadp;		/* head of list of buffers */
extern window_t *curwp;
extern window_t *wheadp;

/*
 * Some compilers define size_t as a unsigned 16 bit number while
 * point_t and off_t might be defined as a signed 32 bit number.
 * malloc(), realloc(), fread(), and fwrite() take size_t parameters,
 * which means there will be some size limits because size_t is too
 * small of a type.
 */
#define MAX_SIZE_T      ((unsigned long) (size_t) ~0)

extern int LINES;
extern int COLS;
extern int MSGLINE;
extern int done;                /* Quit flag. */
extern int msgflag;             /* True if msgline should be displayed. */
extern kill_t scrap;           /* Allocated scrap buffer. */
extern kill_t kill_ring[KILLRING_SIZE];     /* Previous scraps */
extern kill_t shell_ring[SHELLRING_SIZE];     /* Previous shell commands */
extern char_t input[];
extern char msgline[];          /* Message line input/output buffer. */
extern char temp[];             /* Temporary buffer. */
extern char *gtemp;             /* Growable Temporary buffer. */
extern long ngtemp;             /* Size of Growable Temporary buffer. */
extern char searchtext[];
extern int found_point;          /* Page line where found search item is */
extern int search_dir;           /* 1 = fwd, 2 = back */
extern char replace[];
extern keymap_t *key_map;       /* Command key mappings. */
extern keymap_t keymap[];
extern keymap_t *key_return;    /* Command key return */
extern int universal_argument;
extern int numeric_argument;
extern int negated;
extern int submatch;
extern uint32_t input_char;       /* Used if the input char is wanted later. Such as numeric-argument */
extern int undoset_flag;      /* Used to determine if the undo should be set on movegap */
extern char editor_dir[];     /* The directory the editor was opened in. */
extern int record_input;
extern int record_buffer_index;
extern int run_buffer_index;
extern struct tb_event record_buffer[];
extern int execute_kbd_macro;
extern int undo_index;
extern char unicode_buf[7];
extern char character[1];
extern int lastcommand;
extern int currentcommand;
extern int window_mode;
extern int ignorenotbound;
extern char *backup_dir;          /* Backup file supplied with -b */
extern char *switch_command;       /* Command supplied with -s */
extern int lastcol;               /* Last column used with goto-column */
extern int lastline;              /* Last line used with goto-line */
extern char lastchar;             /* Last char used with zap-/jump-to-char */
extern char lastsymb;             /* Last symbol used with delete-between */
extern point_t recentbracket;     /* The bracket you just input */
extern const char* term;
extern dyna_t dynaex;             /* The dynamic expansion struct */
extern int io;

extern void fatal(char *);
extern void msg(char *, ...);
extern void display(window_t *, int);
extern void dispmsg(void);
extern void modeline(window_t *);
extern int utf8_size(char_t);
extern int prev_utf8_char_size(void);
extern void display_utf8(char_t *, int, int, int);
extern point_t lnstart(buffer_t *, point_t);
extern point_t lncolumn(buffer_t *, point_t, int);
extern point_t segstart(buffer_t *, window_t *, point_t, point_t);
extern point_t segnext(buffer_t *, window_t *, point_t, point_t);
extern point_t upup(buffer_t *, window_t *, point_t);
extern point_t dndn(buffer_t *, window_t *, point_t);
extern char_t *get_key(keymap_t *, keymap_t **);
extern int getinput(char *, char *, int, int, int);
extern int getfilename(char *, char *, int);
extern buffer_t * getbuffername(char *, char *, int, int *);
extern void display_prompt_and_response(char *, char *);
extern int growgap(buffer_t *, point_t);
extern point_t movegap(buffer_t *, point_t);
extern point_t pos(buffer_t *, char_t *);
extern char_t *ptr(buffer_t *, point_t);
extern int posix_file(char *);
extern int save(char *);
extern int load_file(char *);
extern int insert_file(char *, int);
extern void undoset(int, int);
extern void undo(void);
extern void redo(void);
extern void backsp(void);
extern void block(void);
extern void iblock(void);
extern void unmark(void);
extern void bottom(void);
extern void cut(void);
extern void copy(void);
extern void copy_cut(int, int, int);
extern void delete(void);
extern void toggle_overwrite_mode(void);
extern void down(void);
extern void insert(void);
extern void insert_str(void);
extern void insert_unicode(void);
extern void left(void);
extern void lnbegin(void);
extern void lnend(void);
extern void paste_internal(int);
extern void paste(void);
extern void clipboard(void);
extern void pgdown(void);
extern void pgup(void);
extern void quit(void);
extern int yesno(int);
extern char yesnomaybeso(char);
extern void quit_ask(void);
extern void redraw(void);
extern void readfile(void);
extern void insertfile(void);
extern void right(void);
extern void top(void);
extern void up(void);
extern void version(void);
extern void wleft(void);
extern void wleftdelete(void);
extern void wright(void);
extern void wrightdelete(void);
extern void writefile(void);
extern void savebuffer(void);
extern void showpos(void);
extern void killtoeol(void);
extern void gotoline(void);
extern void gotocolumn(void);
extern void jumptorow(void);
extern void jumpword(void);
extern void search(int);
extern void search_fwd(void);
extern void search_rev(void);
extern void query_replace(void);
extern void delete_between(void);
extern point_t line_to_point(int);
extern point_t search_forward(buffer_t *, point_t, char *);
extern point_t search_backwards(buffer_t *, point_t, char *);
extern void update_search_prompt(char *, char *);
extern void display_search_result(point_t, int, char *, char *, int *);
extern buffer_t* find_buffer(char *, int, int);
extern void buffer_init(buffer_t *);
extern int delete_buffer(buffer_t *);
extern void next_buffer(void);
extern void prev_buffer(void);
extern void switch_buffer(void);
extern int count_buffers(void);
extern int modified_buffers(void);
extern void killbuffer(void);
extern char* get_buffer_name(buffer_t *);
extern void get_line_stats(int *, int *, buffer_t *);
extern void query_replace(void);
extern window_t *new_window();
extern void one_window(window_t *);
extern void split_window();
extern void tri_split_window();
extern void chop_window();
extern void tri_chop_window();
extern void fib_left();
extern void fib_right();
extern void quad_window();
extern void close_window();
extern void next_window();
extern void delete_other_windows();
extern void free_other_windows(window_t *);
extern void update_display();
extern void w2b(window_t *);
extern void b2w(window_t *);
extern void associate_b2w(buffer_t *, window_t *);
extern void disassociate_b(window_t *);
extern void set_parse_state(buffer_t *, point_t, window_t *, int);
extern int parse_text(buffer_t *, point_t, int);
extern void write_parse_state(window_t *);
extern void dec_skip();
extern void resize_terminal();
extern void insertnewlinebelow();
extern void insertnewline();
extern void inserttab();
extern void inserttabasspace();
extern void recenter();
extern void print_tb(const char *, int, int, uint16_t, uint16_t);
extern void printf_tb(int, int, uint16_t, uint16_t, const char *, ...);
extern void print_to_msgline(const char *);
extern void addch(char);
extern void addstr(const char *);
extern void addchxy(char, int, int, int);
extern void addstrxy(char *, int, int, int);
extern void clrtoeol(int, int);
extern void suspend();
extern void transpose();
extern void transposeword();
extern void lowercaseword();
extern void capitalizeword();
extern void uppercaseword();
extern void zaptochar();
extern void negated_zaptochar();
extern void jumptochar();
extern void negated_jumptochar();
extern void poptomark();
extern void universal_argument_load();
extern void numeric_argument_load();
extern void back_to_indentation();
extern void negate();
extern void forward_bracket();
extern void backward_bracket();
extern void start_kbd_macro();
extern void end_kbd_macro();
extern void run_kbd_macro();
extern void get_popen_data();
extern void open_file_from_shell();
extern void insert_from_shell();
extern void modify_buffer_name(buffer_t *, int);
extern int compare_buffer_name(buffer_t *, buffer_t *);
extern int msgline_editor(struct tb_event, char *, char *, int, int *);
extern int is_file_modified(char *);
extern int file_was_modified_prompt();
extern void insert_control_char();
extern void comment();
extern void comment_at_eol();
extern void resize();
extern void use_kbd_macro(struct tb_event *);
extern void dynamically_expand();
